home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / idlelib / AutoComplete.py < prev    next >
Text File  |  2008-10-05  |  9KB  |  227 lines

  1. """AutoComplete.py - An IDLE extension for automatically completing names.
  2.  
  3. This extension can complete either attribute names of file names. It can pop
  4. a window with all available names, for the user to select from.
  5. """
  6. import os
  7. import sys
  8. import string
  9.  
  10. from configHandler import idleConf
  11.  
  12. import AutoCompleteWindow
  13. from HyperParser import HyperParser
  14.  
  15. import __main__
  16.  
  17. # This string includes all chars that may be in a file name (without a path
  18. # separator)
  19. FILENAME_CHARS = string.ascii_letters + string.digits + os.curdir + "._~#$:-"
  20. # This string includes all chars that may be in an identifier
  21. ID_CHARS = string.ascii_letters + string.digits + "_"
  22.  
  23. # These constants represent the two different types of completions
  24. COMPLETE_ATTRIBUTES, COMPLETE_FILES = range(1, 2+1)
  25.  
  26. class AutoComplete:
  27.  
  28.     menudefs = [
  29.         ('edit', [
  30.             ("Show Completions", "<<force-open-completions>>"),
  31.         ])
  32.     ]
  33.  
  34.     popupwait = idleConf.GetOption("extensions", "AutoComplete",
  35.                                    "popupwait", type="int", default=0)
  36.  
  37.     def __init__(self, editwin=None):
  38.         if editwin == None:  # subprocess and test
  39.             self.editwin = None
  40.             return
  41.         self.editwin = editwin
  42.         self.text = editwin.text
  43.         self.autocompletewindow = None
  44.  
  45.         # id of delayed call, and the index of the text insert when the delayed
  46.         # call was issued. If _delayed_completion_id is None, there is no
  47.         # delayed call.
  48.         self._delayed_completion_id = None
  49.         self._delayed_completion_index = None
  50.  
  51.     def _make_autocomplete_window(self):
  52.         return AutoCompleteWindow.AutoCompleteWindow(self.text)
  53.  
  54.     def _remove_autocomplete_window(self, event=None):
  55.         if self.autocompletewindow:
  56.             self.autocompletewindow.hide_window()
  57.             self.autocompletewindow = None
  58.  
  59.     def force_open_completions_event(self, event):
  60.         """Happens when the user really wants to open a completion list, even
  61.         if a function call is needed.
  62.         """
  63.         self.open_completions(True, False, True)
  64.  
  65.     def try_open_completions_event(self, event):
  66.         """Happens when it would be nice to open a completion list, but not
  67.         really neccesary, for example after an dot, so function
  68.         calls won't be made.
  69.         """
  70.         lastchar = self.text.get("insert-1c")
  71.         if lastchar == ".":
  72.             self._open_completions_later(False, False, False,
  73.                                          COMPLETE_ATTRIBUTES)
  74.         elif lastchar == os.sep:
  75.             self._open_completions_later(False, False, False,
  76.                                          COMPLETE_FILES)
  77.  
  78.     def autocomplete_event(self, event):
  79.         """Happens when the user wants to complete his word, and if neccesary,
  80.         open a completion list after that (if there is more than one
  81.         completion)
  82.         """
  83.         if hasattr(event, "mc_state") and event.mc_state:
  84.             # A modifier was pressed along with the tab, continue as usual.
  85.             return
  86.         if self.autocompletewindow and self.autocompletewindow.is_active():
  87.             self.autocompletewindow.complete()
  88.             return "break"
  89.         else:
  90.             opened = self.open_completions(False, True, True)
  91.             if opened:
  92.                 return "break"
  93.  
  94.     def _open_completions_later(self, *args):
  95.         self._delayed_completion_index = self.text.index("insert")
  96.         if self._delayed_completion_id is not None:
  97.             self.text.after_cancel(self._delayed_completion_id)
  98.         self._delayed_completion_id = \
  99.             self.text.after(self.popupwait, self._delayed_open_completions,
  100.                             *args)
  101.  
  102.     def _delayed_open_completions(self, *args):
  103.         self._delayed_completion_id = None
  104.         if self.text.index("insert") != self._delayed_completion_index:
  105.             return
  106.         self.open_completions(*args)
  107.  
  108.     def open_completions(self, evalfuncs, complete, userWantsWin, mode=None):
  109.         """Find the completions and create the AutoCompleteWindow.
  110.         Return True if successful (no syntax error or so found).
  111.         if complete is True, then if there's nothing to complete and no
  112.         start of completion, won't open completions and return False.
  113.         If mode is given, will open a completion list only in this mode.
  114.         """
  115.         # Cancel another delayed call, if it exists.
  116.         if self._delayed_completion_id is not None:
  117.             self.text.after_cancel(self._delayed_completion_id)
  118.             self._delayed_completion_id = None
  119.  
  120.         hp = HyperParser(self.editwin, "insert")
  121.         curline = self.text.get("insert linestart", "insert")
  122.         i = j = len(curline)
  123.         if hp.is_in_string() and (not mode or mode==COMPLETE_FILES):
  124.             self._remove_autocomplete_window()
  125.             mode = COMPLETE_FILES
  126.             while i and curline[i-1] in FILENAME_CHARS:
  127.                 i -= 1
  128.             comp_start = curline[i:j]
  129.             j = i
  130.             while i and curline[i-1] in FILENAME_CHARS+os.sep:
  131.                 i -= 1
  132.             comp_what = curline[i:j]
  133.         elif hp.is_in_code() and (not mode or mode==COMPLETE_ATTRIBUTES):
  134.             self._remove_autocomplete_window()
  135.             mode = COMPLETE_ATTRIBUTES
  136.             while i and curline[i-1] in ID_CHARS:
  137.                 i -= 1
  138.             comp_start = curline[i:j]
  139.             if i and curline[i-1] == '.':
  140.                 hp.set_index("insert-%dc" % (len(curline)-(i-1)))
  141.                 comp_what = hp.get_expression()
  142.                 if not comp_what or \
  143.                    (not evalfuncs and comp_what.find('(') != -1):
  144.                     return
  145.             else:
  146.                 comp_what = ""
  147.         else:
  148.             return
  149.  
  150.         if complete and not comp_what and not comp_start:
  151.             return
  152.         comp_lists = self.fetch_completions(comp_what, mode)
  153.         if not comp_lists[0]:
  154.             return
  155.         self.autocompletewindow = self._make_autocomplete_window()
  156.         self.autocompletewindow.show_window(comp_lists,
  157.                                             "insert-%dc" % len(comp_start),
  158.                                             complete,
  159.                                             mode,
  160.                                             userWantsWin)
  161.         return True
  162.  
  163.     def fetch_completions(self, what, mode):
  164.         """Return a pair of lists of completions for something. The first list
  165.         is a sublist of the second. Both are sorted.
  166.  
  167.         If there is a Python subprocess, get the comp. list there.  Otherwise,
  168.         either fetch_completions() is running in the subprocess itself or it
  169.         was called in an IDLE EditorWindow before any script had been run.
  170.  
  171.         The subprocess environment is that of the most recently run script.  If
  172.         two unrelated modules are being edited some calltips in the current
  173.         module may be inoperative if the module was not the last to run.
  174.         """
  175.         try:
  176.             rpcclt = self.editwin.flist.pyshell.interp.rpcclt
  177.         except:
  178.             rpcclt = None
  179.         if rpcclt:
  180.             return rpcclt.remotecall("exec", "get_the_completion_list",
  181.                                      (what, mode), {})
  182.         else:
  183.             if mode == COMPLETE_ATTRIBUTES:
  184.                 if what == "":
  185.                     namespace = __main__.__dict__.copy()
  186.                     namespace.update(__main__.__builtins__.__dict__)
  187.                     bigl = eval("dir()", namespace)
  188.                     bigl.sort()
  189.                     if "__all__" in bigl:
  190.                         smalll = eval("__all__", namespace)
  191.                         smalll.sort()
  192.                     else:
  193.                         smalll = filter(lambda s: s[:1] != '_', bigl)
  194.                 else:
  195.                     try:
  196.                         entity = self.get_entity(what)
  197.                         bigl = dir(entity)
  198.                         bigl.sort()
  199.                         if "__all__" in bigl:
  200.                             smalll = entity.__all__
  201.                             smalll.sort()
  202.                         else:
  203.                             smalll = filter(lambda s: s[:1] != '_', bigl)
  204.                     except:
  205.                         return [], []
  206.  
  207.             elif mode == COMPLETE_FILES:
  208.                 if what == "":
  209.                     what = "."
  210.                 try:
  211.                     expandedpath = os.path.expanduser(what)
  212.                     bigl = os.listdir(expandedpath)
  213.                     bigl.sort()
  214.                     smalll = filter(lambda s: s[:1] != '.', bigl)
  215.                 except OSError:
  216.                     return [], []
  217.  
  218.             if not smalll:
  219.                 smalll = bigl
  220.             return smalll, bigl
  221.  
  222.     def get_entity(self, name):
  223.         """Lookup name in a namespace spanning sys.modules and __main.dict__"""
  224.         namespace = sys.modules.copy()
  225.         namespace.update(__main__.__dict__)
  226.         return eval(name, namespace)
  227.